home *** CD-ROM | disk | FTP | other *** search
- IDEAL
- MODEL Tiny ;TINY, cause we are making a COM file
- ────────────────────────────────────────────────────────────────────────────
- CODESEG
- LOCALS
- P386n
-
- MASM
- .STARTUP ;in a COM file, CS = SS = DS = ES = PSPseg at startup
- ;I used .STARTUP here cause I couldn't get it
- ;to do a com file otherwise... =(
- IDEAL
-
- mov sp,offset StackArea + 200h ;setup 200h byte stack (for setup
- ; only!)
- jmp Init_TSR ;Start TSR!
-
- ────────────────────────────────────────────────────────────────────────────
- ; We put all our PERMANENT data right here...
- ────────────────────────────────────────────────────────────────────────────
- MultiIdent = 0D7h ;our identifier - can be any value >= D7h?
- ENVoff = 2ch ;offset in PSP seg to ENVironment block seg
- TrueCode = 0fed8h ;a double check to make sure it's our guy
- ; that's installed
-
- PSPseg dw ? ;ES at the beginning of execution
-
- OldInt10h dd ? ;intercept BIOS calls to detect mode changes
- OldInt1Ch dd ? ;this is called by timer interrupt 8 (IRQ 0)
- OldInt2fh dd ? ;this is the old multi-plex interrupt
-
- TimerActive db 2 ;0= do nothing, not in TEXT video mode
- ;1= display time and message.
-
- Other_Stack dd ? ;save stack SS:SP here
- Our_Stack dd ?
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────
- ; This new Int 10h is just to detect mode changes
- ────────────────────────────────────────────────────────────────────
- PROC Int_10h FAR
- pushf
- call [DWORD CS:OldInt10h] ;execute the interrupt
-
- mov [cs:TimerActive],0 ;assume it GRAPH mode
-
- push ds bx
-
- xor bx,bx
- mov ds,bx
-
- mov bl,[ds:449h] ;get video mode
- cmp bl,3
- ja short @@IsGraph
-
- mov [cs:TimerActive],1
-
- @@IsGraph:
-
- pop bx ds
- iret
- ENDP
- ────────────────────────────────────────────────────────────────────
- ; This Int 1Ch handler does all the dirty work
- ────────────────────────────────────────────────────────────────────
- PROC Int_1Ch FAR
- cmp [CS:TimerActive],0
- je @@END
-
- cli ;an interrupt MAY crash the computer...
- ; cause we're messing with the stack
-
- mov [WORD HIGH cs:Other_Stack],ss ;setup our stack
- mov [WORD LOW cs:Other_Stack],sp
- lss sp,[cs:Our_Stack]
-
- push es cx ax dx di
- cld
-
- mov ax,0b800h
- mov es,ax
- mov di,(80-8) * 2 ;upper right side
-
- mov ah,2 ;read real time clock
- int 1ah ;CH = hours in BCD
- ;CL = minutes, DH= seconds
-
- mov ah,021h ;color blue on green (LAME!)
- mov al,ch
- shr al,4
- add al,"0"
- stosw
- mov al,ch ;print hours
- and al,00001111b
- add al,"0"
- stosw
-
- mov al,":"
- stosw
-
- mov al,cl
- shr al,4
- add al,"0"
- stosw
- mov al,cl ;print minutes
- and al,00001111b
- add al,"0"
- stosw
-
- mov al,":"
- stosw
-
- mov al,dh
- shr al,4
- add al,"0"
- stosw
- mov al,dh ;print seconds
- and al,00001111b
- add al,"0"
- stosw
-
- pop di dx ax cx es
-
- lss sp,[cs:Other_Stack] ;restore other guys stack
- sti
-
- @@END:
- jmp [DWORD cs:OldInt1Ch] ;do original interrupt
- ENDP
- ────────────────────────────────────────────────────────────────────
- ; call Int 2Fh with AH = MultiIdent and you will get back...
- ;
- ; If TSR is installed...
- ;OUT: CF= 0
- ; AX= TRUECODE
- ; BX= PSP seg (use to release memory block)
- ; CX= CS (use to access variables)
- ;
- ; If TSR was NOT previously installed...
- ;OUT: AH= <unchanged>
- ; CF= 1
- ────────────────────────────────────────────────────────────────────
- PROC Int_2Fh FAR
- cmp ah,MultiIdent ;is it our call?
- je short @@Its_Ours
-
- jmp [DWORD cs:OldInt2Fh] ;nope, let it chain through
-
- @@Its_Ours:
- mov ax,TrueCode ;tell 'em that it's REALLY ours
- mov bx,[cs:PSPseg] ;grab PSP segment
- mov cx,cs ;set to current CODESEG
- clc
- retf 2 ;need flags to NOT be restored
- ENDP
-
- dw 50 dup (?) ;a VERY small stack.. enough to push all
- ;extended registers and segment regs..
-
- LABEL The_Stack WORD ;!!! NOTE THAT THE LABEL IS AFTER THE STACK !!!
- ; STACKS GO DOWN!!
-
-
- ────────────────────────────────────────────────────────────────────────────
- ; !!!! EXERYTHING ABOVE THIS POINT REMAINS RESIDENT. BELOW GOES BYEBYE !!!!
- ────────────────────────────────────────────────────────────────────────────
- AXE_POINT: ;where we chop the code.. =)
-
-
-
-
-
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────────────
- ; We put all our SETUP-ONLY data right here...
- ────────────────────────────────────────────────────────────────────────────
-
- MSG_Installed db "TSR was successfully installed.",13,10,0
- MSG_Removed db "TSR is now removed.",13,10,0
-
- ────────────────────────────────────────────────────────────────────────────
- ────────────────────────────────────────────────────────────────────
- ; Prints a ASCIIZ string pointed to by DS:SI
- ────────────────────────────────────────────────────────────────────
- PROC PrintZ NEAR
- push si ax dx
-
- @@PrLoop:
- mov dl,[si]
- inc si
- or dl,dl
- je short @@Done
-
- mov ah,2
- int 21h
- jmp short @@PrLoop
-
- @@Done:
- pop dx ax si
- ret
- ENDP
-
- ────────────────────────────────────────────────────────────────────
- ; Initializes the TSR or, if it's already installed, removes it.
- ────────────────────────────────────────────────────────────────────
- PROC Init_TSR NEAR
- mov ax,cs
- mov ds,ax
- mov [PSPseg],es ;save PSPseg
-
- mov [WORD LOW Our_Stack],offset The_Stack ;setup our stack
- mov [WORD HIGH Our_Stack],cs
-
- mov ah,MultiIdent ;check to see if we are already installed
- int 2fh
- jc short @@Install ;not there
- cmp ax,TrueCode ;is it REALLY installed?
- jne short @@Install
-
- push bx ;BX = PSPseg of other guy
- ──
- push ds
- mov ds,cx ;DS = other guys CS
-
- mov bx,10h ;uninstall other guys stuff
- mov di,offset OldInt10h ;use same offsets, since it's the same
- call Restore_int ; program... =)
-
- mov bx,1ch
- mov di,offset OldInt1ch
- call Restore_int
-
- mov bx,2fh
- mov di,offset OldInt2fh
- call Restore_int
- pop ds
- ──
- pop es ;from BX's push.. get the PSPseg of OTHER GUY
- mov ah,49h
- int 21h ;release that memory block
-
- mov ax,cs
- mov ds,ax
- mov si,offset Msg_Removed
- call PrintZ
-
- mov ax,4c00h
- int 21h ;exit program
-
- @@Install:
- mov es,[cs:ENVoff] ;get segment of Environment block
- mov ah,49h
- int 21h ;release it (WE DON'T NEED IT)
- ──
- mov ax,cs
- mov ds,ax
-
- mov bx,10h
- mov di,offset OldInt10h
- mov dx,offset Int_10h
- call Set_Int
-
- mov bx,1ch
- mov di,offset OldInt1ch
- mov dx,offset Int_1ch
- call Set_Int
-
- mov bx,2fh
- mov di,offset OldInt2fh
- mov dx,offset Int_2fh
- call Set_Int
- ──
- mov si,offset MSG_Installed
- call PrintZ
- ──
- mov dx,offset AXE_Point
- shr dx,4
- inc dx
- mov ax,3100h ;function KEEP (advanced TSR)
- int 21h ; al = return code, dx = paragraphs to keep
- ENDP
-
- ────────────────────────────────────────────────────────────────────
- ; bx = interrupt # to replace
- ;
- ;DS:DI = where to store old interrupt
- ;DS:DX = offset to new INTerrupt
- ────────────────────────────────────────────────────────────────────
- PROC Set_Int NEAR
- push es ecx bx
-
- xor cx,cx
- mov es,cx
- shl bx,2
-
- mov ecx,[es:bx] ;grab old int
- mov [di],ecx ;save it
-
- cli
- mov [WORD es:bx ],dx ;store new int
- mov [WORD es:bx+2],ds
- sti
-
- pop bx ecx es
- ret
- ENDP
- ────────────────────────────────────────────────────────────────────
- ; bx = interrupt # to restore
- ;
- ;DS:DI = where old interrupt is stored
- ────────────────────────────────────────────────────────────────────
- PROC Restore_Int NEAR
- push es ecx bx
-
- xor cx,cx
- mov es,cx
- shl bx,2
-
- cli
- mov ecx,[di] ;grab old SAVED int
- mov [es:bx],ecx ;restore it
- sti
-
- pop bx ecx es
- ret
- ENDP
-
- StackArea: ;where the stack for initialization goes
-
- END
-